package com.homedo.microservice.open.service.gateway.manager.web.gateway.service;

import com.google.common.collect.Lists;
import com.homedo.common.bean.data.enums.ResponseEnum;
import com.homedo.common.bean.vo.context.UserContext;
import com.homedo.common.exception.HomedoException;
import com.homedo.common.util.Detect;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.enums.forroute.StatusEnum4Route;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.enums.forrouteservice.StatusEnum4RouteService;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.enums.forrouteserviceurl.StatusEnum4RouteServiceUrl;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.Route;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.RouteServiceUrl;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.RouteVersion;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.enhanced.RouteEnhanced;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.enhanced.RouteServiceEnhanced;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.enhanced.RouteServiceUrlEnhanced;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.enhanced.RouteVersionEnhanced;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.support.ApplicationNameHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PullService {
    @Autowired
    private RouteService routeService;
    @Autowired
    private RouteServiceService routeServiceService;
    @Autowired
    private RouteVersionService routeVersionService;
    @Autowired
    private RouteServiceUrlService routeServiceUrlService;


    public void dealPullIn(String routeId, String version, String url, int urlCount, UserContext userContext) {
        this.checkPullIn(routeId, url, urlCount);

        Route route = routeService.getById(routeId, userContext);
        if (route == null) {
            throw new HomedoException("[不存在此路由:" + routeId + "]");
        }
        RouteServiceEnhanced routeServiceEnhanced = routeServiceService.getEnhanced(route.getServiceId(), userContext);

        String serviceId = routeServiceEnhanced.getId();
        boolean createNewRouteVersion = false;

        if (Detect.notEmpty(version)) {//版本不为空
            RouteVersion routeVersionRecord = new RouteVersion();
            routeVersionRecord.setRouteId(routeId);
            routeVersionRecord.setVersion(version);

            RouteVersion routeVersion = routeVersionService.getOneByRecord(routeVersionRecord, userContext);

            if (routeVersion == null) {//版本不存在即创建版本
                serviceId = this.createRouteVersion(routeId, version, url, routeServiceEnhanced.getHealthUrl(), userContext);//创建新路由版本
                createNewRouteVersion = true;
            } else {
                serviceId = routeVersion.getServiceId();
            }
        }

        if (!createNewRouteVersion) {
            this.dealPullInRouteService(serviceId, url, userContext);//拉入服务--非新建版本
        }

        this.dealPullOutOtherRouteService(routeId, serviceId, url, userContext);//拉出别的版本下的当前服务器
        this.dealMainRoute(routeId, version, urlCount, userContext);//处理默认路由
    }

    public void dealPullOut(String routeId, String url, UserContext userContext) {
        this.checkPullOut(routeId, url);

        RouteEnhanced routeEnhanced = routeService.getEnhanced(routeId, userContext);
        if (routeEnhanced == null) {
            throw new HomedoException("[不存在此路由:" + routeId + "]");
        }

        List<RouteServiceEnhanced> routeServiceEnhanceds = Lists.newArrayList();
        routeServiceEnhanceds.add(routeEnhanced.getRouteServiceEnhanced());

        if (Detect.notEmpty(routeEnhanced.getRouteVersionEnhanceds())) {
            routeServiceEnhanceds.addAll(routeEnhanced.getRouteVersionEnhanceds().stream().map(RouteVersionEnhanced::getRouteServiceEnhanced).collect(Collectors.toList()));
        }

        routeServiceEnhanceds.forEach(e -> {
            if (Detect.notEmpty(e.getRouteServiceUrlEnhanceds())) {
                e.getRouteServiceUrlEnhanceds().forEach(u -> {
                    if (u.getUrl().equals(url)) {
                        RouteServiceUrl updateRouteServiceUrl = new RouteServiceUrl();
                        updateRouteServiceUrl.setId(u.getId());
                        updateRouteServiceUrl.setUpdateTime(new Date());
                        updateRouteServiceUrl.setStatus((int) StatusEnum4RouteServiceUrl.INVALID.getCode());

                        routeServiceUrlService.updateByPrimaryKeySelective(updateRouteServiceUrl, userContext);
                    }
                });
            }
        });

    }

    private void checkPullOut(String routeId, String url) {
        if (!Detect.notEmpty(routeId) || !Detect.notEmpty(url)) {
            throw new HomedoException(ResponseEnum.PARAM_ERROR);
        }
    }


    private void checkPullIn(String routeId, String url, int urlCount) {
        if (!Detect.notEmpty(routeId) || !Detect.notEmpty(url) || urlCount < 1) {
            throw new HomedoException(ResponseEnum.PARAM_ERROR);
        }
    }

    private void dealMainRoute(String routeId, String version, int urlcount, UserContext userContext) {
        if (!Detect.notEmpty(version)) {
            return;
        }

        RouteVersion routeVersionRecord = new RouteVersion();
        routeVersionRecord.setRouteId(routeId);
        routeVersionRecord.setVersion(version);

        RouteVersion routeVersion = routeVersionService.getOneByRecord(routeVersionRecord, userContext);
        List<RouteServiceUrlEnhanced> routeServiceUrlEnhanceds = routeServiceUrlService.getEnhanceds4Services(Lists.newArrayList(routeVersion.getServiceId()), userContext);

        if (routeServiceUrlEnhanceds.size() < urlcount) {
            return;
        }

        RouteEnhanced routeEnhanced = routeService.getEnhanced(routeId, userContext);
        RouteServiceUrl deleteRouteServiceUrl = new RouteServiceUrl();
        deleteRouteServiceUrl.setServiceId(routeEnhanced.getRouteServiceEnhanced().getId());

        routeServiceUrlService.delete(deleteRouteServiceUrl, userContext);//清空主路由服务列表

        routeServiceUrlEnhanceds.forEach(e -> {
            RouteServiceUrl routeServiceUrl = new RouteServiceUrl();
            routeServiceUrl.setServiceId(routeEnhanced.getRouteServiceEnhanced().getId());
            routeServiceUrl.setUrl(e.getUrl());
            routeServiceUrl.setCreateTime(new Date());
            routeServiceUrl.setUpdateTime(new Date());
            routeServiceUrl.setStatus((int) StatusEnum4RouteServiceUrl.EFFECTIVE.getCode());
            routeServiceUrl.setComment("[自动创建]");

            routeServiceUrlService.saveRouteServiceUrl(routeServiceUrl, userContext);
        });

        routeVersionService.deleteById(routeVersion.getId(), userContext);//子版本全部发布即用主版本替换子版本
        RouteServiceUrl deleteVersionRouteServiceUrl = new RouteServiceUrl();
        deleteVersionRouteServiceUrl.setServiceId(routeVersion.getServiceId());
        routeServiceUrlService.delete(deleteVersionRouteServiceUrl, userContext);
        routeServiceService.deleteById(routeVersion.getServiceId(), userContext);
    }

    private void dealPullOutOtherRouteService(String routeId, String serviceId, String url, UserContext userContext) {
        RouteEnhanced routeEnhanced = routeService.getEnhanced(routeId, userContext);
        List<RouteServiceEnhanced> routeServiceEnhanceds = Lists.newArrayList();
        routeServiceEnhanceds.add(routeEnhanced.getRouteServiceEnhanced());

        if (Detect.notEmpty(routeEnhanced.getRouteVersionEnhanceds())) {
            routeServiceEnhanceds.addAll(routeEnhanced.getRouteVersionEnhanceds().stream().map(RouteVersionEnhanced::getRouteServiceEnhanced).collect(Collectors.toList()));
        }

        routeServiceEnhanceds.forEach(e -> {
            if (!e.getId().equals(serviceId) && Detect.notEmpty(e.getRouteServiceUrlEnhanceds())) {
                Iterator<RouteServiceUrlEnhanced> routeServiceUrlEnhancedIterator = e.getRouteServiceUrlEnhanceds().iterator();
                while (routeServiceUrlEnhancedIterator.hasNext()) {
                    RouteServiceUrlEnhanced routeServiceUrlEnhanced = routeServiceUrlEnhancedIterator.next();

                    if (routeServiceUrlEnhanced.getUrl().equals(url)) {

                        routeServiceUrlService.deleteById(routeServiceUrlEnhanced.getId(), userContext);//从其它路由下移除服务器
                        routeServiceUrlEnhancedIterator.remove();
                    }
                }
            }
        });

        if (Detect.notEmpty(routeEnhanced.getRouteVersionEnhanceds())) {
            routeEnhanced.getRouteVersionEnhanceds().forEach(e -> {
                if (!Detect.notEmpty(e.getRouteServiceEnhanced().getRouteServiceUrlEnhanceds())) {
                    routeVersionService.deleteById(e.getId(), userContext);//删除空版本
                    routeServiceService.deleteById(e.getRouteServiceEnhanced().getId(), userContext);//删除空版本对应的服务组
                }
            });
        }

        if (!Detect.notEmpty(routeEnhanced.getRouteServiceEnhanced().getRouteServiceUrlEnhanceds()) && Detect.notEmpty(routeEnhanced.getRouteVersionEnhanceds())) {
            List<String> urls = Lists.newArrayList();

            int versionLength = routeEnhanced.getRouteVersionEnhanceds().size();
            for (int i = versionLength - 1; i > -1; i--) {
                RouteVersionEnhanced routeVersionEnhanced = routeEnhanced.getRouteVersionEnhanceds().get(i);
                if (Detect.notEmpty(routeVersionEnhanced.getRouteServiceEnhanced().getRouteServiceUrlEnhanceds())) {
                    routeVersionEnhanced.getRouteServiceEnhanced().getRouteServiceUrlEnhanceds().forEach(e -> {
                        urls.add(e.getUrl());//拿最早一个版本的服务列表作为主服务列表
                    });
                    break;
                }
            }

            if (Detect.notEmpty(urls)) {
                urls.forEach(e -> {
                    RouteServiceUrl routeServiceUrl = new RouteServiceUrl();
                    routeServiceUrl.setServiceId(routeEnhanced.getRouteServiceEnhanced().getId());
                    routeServiceUrl.setUrl(e);
                    routeServiceUrl.setCreateTime(new Date());
                    routeServiceUrl.setUpdateTime(new Date());
                    routeServiceUrl.setStatus((int) StatusEnum4RouteServiceUrl.EFFECTIVE.getCode());
                    routeServiceUrl.setComment("[自动创建]");

                    routeServiceUrlService.saveRouteServiceUrl(routeServiceUrl, userContext);
                });
            }
        }

    }


    private void dealPullInRouteService(String serviceId, String url, UserContext userContext) {
        RouteServiceUrl routeServiceUrl = new RouteServiceUrl();
        routeServiceUrl.setServiceId(serviceId);
        routeServiceUrl.setUrl(url);

        routeServiceUrl = routeServiceUrlService.getOneByRecord(routeServiceUrl, userContext);
        if (routeServiceUrl == null) {
            routeServiceUrl = new RouteServiceUrl();
            routeServiceUrl.setServiceId(serviceId);
            routeServiceUrl.setUrl(url);
            routeServiceUrl.setCreateTime(new Date());
            routeServiceUrl.setUpdateTime(new Date());
            routeServiceUrl.setComment("[自动创建]");
            routeServiceUrl.setStatus((int) StatusEnum4RouteServiceUrl.EFFECTIVE.getCode());

            routeServiceUrlService.saveRouteServiceUrl(routeServiceUrl, userContext);//创建服务地址
        } else {
            RouteServiceUrl updateRouteServiceUrl = new RouteServiceUrl();
            updateRouteServiceUrl.setId(routeServiceUrl.getId());
            updateRouteServiceUrl.setStatus((int) StatusEnum4RouteServiceUrl.EFFECTIVE.getCode());
            updateRouteServiceUrl.setUpdateTime(new Date());

            routeServiceUrlService.updateByPrimaryKeySelective(updateRouteServiceUrl, userContext);
        }
    }

    private String createRouteVersion(String routeId, String version, String url, String healthUrl, UserContext userContext) {
        com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.RouteService routeServicePo = new com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.RouteService();

        routeServicePo.setId("svg" + new Date().getTime());
        routeServicePo.setApplicationName(ApplicationNameHolder.get());
        routeServicePo.setStatus((int) StatusEnum4RouteService.EFFECTIVE.getCode());
        routeServicePo.setComment("[自动创建]");
        routeServicePo.setCreateTime(new Date());
        routeServicePo.setUpdateTime(new Date());
        routeServicePo.setHealthUrl(healthUrl);

        routeServiceService.save(routeServicePo, userContext);//创建服务组

        RouteServiceUrl routeServiceUrl = new RouteServiceUrl();
        routeServiceUrl.setServiceId(routeServicePo.getId());
        routeServiceUrl.setUrl(url);
        routeServiceUrl.setCreateTime(new Date());
        routeServiceUrl.setUpdateTime(new Date());
        routeServiceUrl.setComment("[自动创建]");
        routeServiceUrl.setStatus((int) StatusEnum4RouteServiceUrl.EFFECTIVE.getCode());

        routeServiceUrlService.saveRouteServiceUrl(routeServiceUrl, userContext);//创建服务地址

        RouteVersion routeVersion = new RouteVersion();
        routeVersion.setVersion(version);
        routeVersion.setRouteId(routeId);
        routeVersion.setServiceId(routeServicePo.getId());
        routeVersion.setCreateTime(new Date());
        routeVersion.setUpdateTime(new Date());
        routeVersion.setComment("[自动创建]");
        routeVersion.setStatus((int) StatusEnum4Route.EFFECTIVE.getCode());

        routeVersionService.save(routeVersion, userContext);//创建路由版本

        return routeServicePo.getId();
    }
}
